<template>
  <div class="myMessage-title">
    我的消息
  </div>
  <div class="myMessage-content" v-if="router.currentRoute.value.params.user_id != '0'">
    <div class="content-left">
      <div class="left-title">
        近期消息
      </div>
      <n-scrollbar style="max-height: calc(100% - 37px)">
        <div class="user-item" v-for="item in chatUserData" :key="item.news_id" @click="selectUser(item)"
          :class="item.recent_user_id == Number(router.currentRoute.value.params.user_id) ? 'active-user-item' : ''">
          <n-avatar round :size="40" :src="'/api/' + item.avatar" />
          <div class="user-name">
            <div class="name">{{ item.username }}</div>
            <div class="last-word">{{ item.last_msg }}</div>
          </div>
          <div class="user-item-tip" v-if="item.unread_msg_count > 0">
            {{ item.unread_msg_count }}
          </div>
          <div class="item-close" @click.stop="deleteRecentChatUser(item)">
            <n-icon :component="CloseOutline" size="20" />
          </div>
        </div>
      </n-scrollbar>
    </div>
    <div class="content-right">
      <div class="right-title">
        {{ currentUserData.username }}
      </div>
      <div class="chat-content">
        <n-scrollbar style="max-height: 100%" ref="scroll">
          <div style="width: 100%;height: 38px;"></div>
          <template v-for="item in chatDataList" :key="item.chat_id">
            <div v-if="item.is_show_time" class="msg-time">
              {{ item.chat_time }}
            </div>
            <div class="msg-item" :class="item.is_send ? 'is-me' : 'not-me'">
              <n-avatar round :size="30" :src="'/api/' + myAvatar" v-if="item.is_send" />
              <n-avatar round :size="30" :src="'/api/' + currentUserData.avatar" v-else />
              <div v-if="!item.is_image" class="message" @contextmenu.prevent="showMenu($event, item)">{{ item.chat_content }}</div>
              <n-image v-else width="150" :lazy="true" :src="'/api/' + item.chat_content" style="margin-right: 10px;" @contextmenu.prevent="showMenu($event, item)"/>
              <!-- 撤销和删除按钮 -->
              <div class="chat-Menu" v-if="isShowMenu" :style="{'left': Menu_left + 'px', 'top': Menu_top + 'px'}">
                <div class="menu-item" @click="copylMsg">复制</div>
                <div class="menu-item" v-if="isCancel" @click="cancelMsg">撤销</div>
                <div class="menu-item" @click="deleteMsg">删除</div>
              </div>
            </div>
          </template>
        </n-scrollbar>
      </div>
      <div class="chat-input">
        <div class="input-icon">
          <n-upload
            action="api/upload"
            accept="image/*"
            response-type="json"
            :show-file-list="false"
            @finish="handleFinish"
            @error="handleError"
          >
            <n-button quaternary size="small">
              <template #icon>
                <n-icon :component="ImageOutline"></n-icon>
              </template>
            </n-button>
          </n-upload>
          <!-- // 表情按钮 -->
          <V3Emoji :recent="true" :theme="osThemeDark ? 'dark' : ''" :fulldata="true" @click-emoji="appendText"
            fix-pos="upright">
            <n-button quaternary size="small">
              <template #icon>
                <n-icon :component="HappyOutline"></n-icon>
              </template>
            </n-button>
          </V3Emoji>
        </div>
        <n-input v-model:value="chatValue" type="textarea" placeholder="请输入" show-count maxlength="300"
          style="height: 60px;" autosize />
        <div class="input-send">
          <n-button type="primary" size="small" style="width: 80px;" @click="sendMsg">
            发送
          </n-button>
        </div>
      </div>
    </div>
  </div>
  <div class="empty-content" v-else>
    <n-empty description="暂无聊天记录"></n-empty>
  </div>
</template>

<script setup lang='ts'>
import { CloseOutline, ImageOutline, HappyOutline } from '@vicons/ionicons5'
import { getUserChat, cancelChat, deleteChat, getRecentChat, deleteRecentChat } from "../../api/message"
import V3Emoji from "vue3-emoji"
import 'vue3-emoji/dist/style.css'
import { UploadFileInfo } from 'naive-ui'
import { ref, onMounted, watch } from "vue"
import { useRouter } from "vue-router"
import { useStore } from "../../store"
const store = useStore()
const router = useRouter()

// 创建WebSocket连接
const user_id = localStorage.getItem("user_id")
var socket = new WebSocket(`ws://${window.location.host}/ws/room/${user_id}`)

const osThemeDark = ref(true)
const myAvatar = ref("")
const chatValue = ref('')
const chatDataList = ref<any>([])
const scroll = ref()
const isShowChatTime = ref(true)
const isShowMenu = ref(false)
const Menu_left = ref("")
const Menu_top = ref("")
const isCancel = ref(false)
const chatUserData = ref<any>([])
const currentUserData = ref<any>({})
const currentChatMsg = ref<any>({})

// 监听消息
socket.onmessage = (e) => {
  const res_data = JSON.parse(e.data)
  if(res_data.from_user_id == Number(router.currentRoute.value.params.user_id) || res_data.is_send){
    // 自己发送的消息
    chatDataList.value.push(res_data)
  }else{
    // 接收的消息
    let allUnRead = 0
    chatUserData.value.forEach((item:any) => {
      if(item.recent_user_id == res_data.from_user_id)
      {
        item.unread_msg_count = item.unread_msg_count + 1
        item.last_msg = res_data.chat_content
      }
      allUnRead += item.unread_msg_count
    })
    store.setUnReadMsg(allUnRead)
  }
  isShowChatTime.value = false
  setTimeout(() => {
    scroll.value.scrollBy(0, 100000000)
  }, 200);
}

const sendMsg = async () => {
  const from_user_id = Number(localStorage.getItem("user_id"))
  const to_user_id = Number(router.currentRoute.value.params.user_id)
  socket.send(JSON.stringify({
    from_user_id,
    to_user_id,
    chat_content: chatValue.value,
    is_image: false,
    is_show_time: isShowChatTime.value,
  }))
  chatUserData.value.forEach((e:any) => {
    if(e.recent_user_id == to_user_id){
      e.last_msg = chatValue.value
      e.unread_msg_count = 0
    }
  })
  chatValue.value = ""
}

// 选择表情
const appendText = (value: any) => {
  chatValue.value = chatValue.value + value.emoji
}

// 上传成功回调
const handleFinish = (options: { file: UploadFileInfo, event?: ProgressEvent}) => {
  const imageUrl = (options.event?.target as XMLHttpRequest).response?.url
  sendImage(imageUrl)
}

const sendImage = async(imageUrl:string) => {
  const from_user_id = Number(localStorage.getItem("user_id"))
  const to_user_id = Number(router.currentRoute.value.params.user_id)
  socket.send(JSON.stringify({
    from_user_id,
    to_user_id,
    chat_content: imageUrl,
    is_image: true,
    is_show_time: isShowChatTime.value,
  }))
  chatUserData.value.forEach((e:any) => {
    if(e.recent_user_id == to_user_id){
      e.last_msg = "[图片]"
      e.unread_msg_count = 0
    }
  })
}

// 上传失败
const handleError = () => {
  window.$message.warning("上传失败")
}

const showMenu = (e:any, item:any) => {
  currentChatMsg.value = item
  if(item.to_chat_id){
    isCancel.value = true
  }else{
    isCancel.value = false
  }
  isShowMenu.value = true
  // 定位
  Menu_top.value = e.pageY
  Menu_left.value = e.pageX
}

const addCloseMenu = () => {
  // 添加监听器，用于其他位置点击时，关闭打开的右键菜单,并清空获取的key
  document.addEventListener('click', () => {
    isShowMenu.value = false
  })
  // 添加监听器，用于点击菜单内按钮时，关闭打开的右键菜单,并清空获取的key
  document.addEventListener('mousedown', (e) => {
    const {button} = e
    if (button === 2) {
      isShowMenu.value = false
    }
  })
}

const copylMsg = () => {
  const text = currentChatMsg.value.chat_content
  navigator.clipboard.writeText(text)
  window.$message.success("复制成功")
}

const cancelMsg = async() => {
  await cancelChat({
    chat_id: currentChatMsg.value.chat_id,
    to_chat_id: currentChatMsg.value.to_chat_id,
  })
  chatDataList.value.splice(chatDataList.value.indexOf(currentChatMsg.value), 1)
}
const deleteMsg = async() => {
  await deleteChat({
    chat_id: currentChatMsg.value.chat_id,
  })
  chatDataList.value.splice(chatDataList.value.indexOf(currentChatMsg.value), 1)
}

const selectUser = async(item:any) => {
  router.push(`/message/myMessage/${item.recent_user_id}`)
}

const deleteRecentChatUser = async(item:any) => {
  await deleteRecentChat(item.news_id)
  chatUserData.value.splice(chatUserData.value.indexOf(item), 1)
  if(chatUserData.value.length == 0){
    router.push("/message/myMessage/0")
  }else{
    router.push(`/message/myMessage/${chatUserData.value[0].recent_user_id}`)
  }
}

onMounted(async () => {
  // init()
  addCloseMenu()
  osThemeDark.value = localStorage.getItem("osTheme") == "dark" ? true : false
  myAvatar.value = localStorage.getItem("avatar") as string
  const from_user_id = Number(localStorage.getItem("user_id"))
  let to_user_id = Number(router.currentRoute.value.params.user_id)
  const recent_news = await getRecentChat(from_user_id)
  if(recent_news.code == "200"){
    chatUserData.value = recent_news.data
  }else{
    window.$message.error(recent_news.message)
  }
  // 判断是否有近期消息
  if(to_user_id == 0 && chatUserData.value.length > 0){
    router.push(`/message/myMessage/${chatUserData.value[0].recent_user_id}`)
    to_user_id = chatUserData.value[0].recent_user_id
  }
  if(to_user_id == 0 && chatUserData.value.length == 0){
    return
  }
  const res_chat = await getUserChat({
    from_user_id,
    to_user_id,
  })
  if (res_chat.code === "200") {
    chatDataList.value = res_chat.data.chat_data
    currentUserData.value = res_chat.data.user_data
  } else {
    window.$message.error(res_chat.message)
  }
  let chatFlag = false
  chatUserData.value.forEach((e:any) => {
    if(e.recent_user_id == to_user_id){
      chatFlag = true
    }
  })
  if(!chatFlag){
    chatUserData.value.push({
      news_id: 0,
      recent_user_id: to_user_id,
      last_msg: "",
      avatar: currentUserData.value.avatar,
      username: currentUserData.value.username,
      unread_msg_count: 0
    })
  }
  setTimeout(() => {
    scroll.value.scrollBy(0, 100000000)
  }, 200);
  
})

watch(() => router.currentRoute.value.params.user_id, async(newValue) => {
  if(newValue){
    const res_chat = await getUserChat({
      from_user_id: Number(localStorage.getItem("user_id")),
      to_user_id: Number(newValue),
    })
    if (res_chat.code === "200") {
      chatDataList.value = res_chat.data.chat_data
      currentUserData.value = res_chat.data.user_data
    } else {
      window.$message.error(res_chat.message)
    }
    let allUnRead = 0
    chatUserData.value.forEach((e:any) => {
      if(e.recent_user_id == Number(newValue)){
        e.unread_msg_count = 0
      }
      allUnRead += e.unread_msg_count
    })
    store.setUnReadMsg(allUnRead)
    setTimeout(() => {
      scroll.value.scrollBy(0, 100000000)
    }, 200);
  }
}, {
  immediate: true,
})

watch(() => store.osTheme, (newValue) => {
  osThemeDark.value = newValue=="dark"?true:false
})

</script>

<style lang='scss' scoped>
.myMessage-title {
  width: 100%;
  height: 50px;
  display: flex;
  align-items: center;
  border-radius: 5px;
  background-color: var(--bs-content-background);
  padding-left: 20px;
  box-sizing: border-box;
  margin-top: 10px;
  margin-bottom: 10px;
  box-shadow: 0 2px 4px 0 rgba(85, 85, 85, 0.54);
}

.myMessage-content {
  // margin-top: 10px;
  width: 100%;
  height: calc(100% - 80px);
  background-color: var(--bs-content-background);
  border-radius: 5px;
  display: flex;
  box-shadow: 0 2px 4px 0 rgba(85, 85, 85, 0.54);

  .content-left {
    width: 240px;
    height: 100%;
    border-right: 1px solid var(--bs-chat-divider);

    .left-title {
      font-size: 12px;
      padding-left: 24px;
      line-height: 35px;
      height: 36px;
      border-bottom: 1px solid var(--bs-chat-divider);
    }

    .user-item {
      position: relative;
      width: 100%;
      height: 78px;
      padding: 19px 24px;
      box-sizing: border-box;
      cursor: pointer;
      display: flex;
      overflow: hidden;

      .user-name {
        margin-left: 8px;
        display: flex;
        flex-direction: column;
        justify-content: space-between;
        height: 100%;

        .name {
          font-size: 14px;
        }

        .last-word {
          font-size: 12px;
          color: #bbbbbb;
          width: 144px;
          overflow: hidden;
          white-space: nowrap;
          text-overflow: ellipsis;
        }
      }

      .item-close {
        position: absolute;
        left: -5px;
        top: 0;
        height: 100%;
        transform: translateX(-100%);
        display: flex;
        align-items: center;
        transition: all 0.3s;
      }
      .user-item-tip{
        line-height: 16px;
        font-size: 12px;
        border-radius: 8px;
        height: 16px;
        min-width: 16px;
        top: 20px;
        right: 8px;
        padding: 0 4px;
        text-align: center;
        position: absolute;
        background-color: #fb7299;
        box-sizing: border-box;
      }
    }

    .active-user-item {
      background-color: var(--bs-hover-background);
    }

    .user-item:hover {
      background-color: var(--bs-hover-background);

      .item-close {
        left: 20px;
      }
    }
  }

  .content-right {
    width: 580px;
    height: 100%;

    .right-title {
      height: 36px;
      display: flex;
      justify-content: center;
      align-items: center;
      border-bottom: 1px solid var(--bs-chat-divider);
      font-size: 14px;
    }

    .chat-content {
      width: 100%;
      height: calc(100% - 196px);
      border-bottom: 1px solid var(--bs-chat-divider);
      background-color: var(--bs-chat-background);

      .msg-item {
        position: relative;
        width: 100%;
        min-height: 50px;
        padding: 0 16px 16px;
        box-sizing: border-box;
        display: flex;

        .message {
          margin: 0 10px;
          font-size: 14px;
          line-height: 1.5;
          min-height: 34px;
          max-width: 480px;
          padding: 8px 16px;
          word-break: break-all;
          overflow: hidden;
          background: var(--bs-chat-text-background);
          box-sizing: border-box;
        }
        .chat-Menu{
          overflow: hidden;
          position: fixed;
          display: flex;
          flex-direction: column;
          background-color: var(--bs-select-bg);
          border-radius: 6px;          
          .menu-item{
            width: 100px;
            cursor: pointer;
            padding: 6px 15px;
            font-size: 13px;
          }
          .menu-item:hover{
            background-color: var(--bs-hover-background);
          }
        }
      }

      .is-me {
        flex-direction: row-reverse;

        .message {
          border-radius: 16px 0 16px 16px;
        }
      }

      .not-me {
        .message {
          border-radius: 0 16px 16px 16px;
        }
      }
      .msg-time{
        width: 100%;
        text-align: center;
        padding: 15px 0;
        font-size: 12px;
        color: gray;
      }
    }

    .chat-input {
      width: 100%;
      height: 160px;
      padding: 0 16px;
      box-sizing: border-box;
      display: flex;
      flex-direction: column;

      .input-icon {
        width: 76px;
        padding: 10px 0;
        display: flex;
        justify-content: flex-start;
      }

      .input-send {
        height: 46px;
        display: flex;
        justify-content: flex-end;
        align-items: center;
      }
    }
  }
}
.empty-content{
  width: 100%;
  height: calc(100% - 80px);
  background-color: var(--bs-content-background);
  border-radius: 5px;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 2px 4px 0 rgba(85, 85, 85, 0.54);
}
</style>
